package ChatRoom;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;
import java.net.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

public class TCPServerFrame extends JFrame implements ActionListener, Runnable, TalkServerReceiveHelperListener {
    public static SocketMode SM = null;
    // 发送信息的文本框
    private final JTextField tfSendMessage = new JTextField();
    // 保存聊天信息
    private final JTextArea taTalkMessage = new JTextArea();
    // 套接字地址对象
    private InetSocketAddress inetSocketAddress = null;
    // 是否需要退出服务器端
    private boolean isExitServer = false;
    // 是否服务器端主动关闭
    private boolean isServerClose = false;
    // ServerSocket
    private ServerSocket ss = null;
    // 保存已连接的套接字
    public final CopyOnWriteArrayList<Socket> socketList = new CopyOnWriteArrayList<>();
    private final ConcurrentHashMap<Socket, String> clientNames = new ConcurrentHashMap<>();

    public TCPServerFrame() {
        super("聊天室---服务器");
    }

    public void initFrame() {
        try {
            inetSocketAddress = new InetSocketAddress(InetAddress.getLocalHost(), 2000);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

        this.getContentPane().setBackground(new Color(240, 240, 240));
        Font defaultFont = new Font("Segue UI", Font.PLAIN, 14);

        // 发送面板
        JPanel sendPanel = new JPanel();
        sendPanel.setPreferredSize(new Dimension(400, 80));
        sendPanel.setBackground(new Color(255, 255, 255));
        sendPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 15)); // 设置流式布局
        this.add(sendPanel, BorderLayout.NORTH);

        // 发送标签
        JLabel lblSend = new JLabel("发送：");
        lblSend.setFont(defaultFont);
        sendPanel.add(lblSend);

        // 发送信息文本框
        tfSendMessage.setPreferredSize(new Dimension(260, 30));
        tfSendMessage.setFont(defaultFont);
        tfSendMessage.setBackground(Color.WHITE);
        tfSendMessage.setBorder(BorderFactory.createLineBorder(new Color(180, 180, 180)));
        sendPanel.add(tfSendMessage);

        // 发送按钮
        JButton btnSend = new JButton("发送");
        btnSend.setActionCommand("send");
        btnSend.setFont(defaultFont);
        btnSend.setBackground(new Color(80, 180, 15));
        btnSend.setForeground(Color.WHITE);
        btnSend.setFocusPainted(false);
        btnSend.addActionListener(this);
        sendPanel.add(btnSend);

        // 服务器信息标签
        String serverInfo = "服务器：" + inetSocketAddress.getAddress().getHostAddress() + " 端口号：" + inetSocketAddress.getPort();
        JLabel lblServerInfo = new JLabel(serverInfo);
        lblServerInfo.setFont(defaultFont);
        lblServerInfo.setForeground(new Color(60, 60, 60));
        sendPanel.add(lblServerInfo);

        // 聊天信息区域
        taTalkMessage.setLineWrap(true);
        taTalkMessage.setWrapStyleWord(true);
        taTalkMessage.setFont(defaultFont);
        taTalkMessage.setBackground(new Color(245, 245, 245));
        taTalkMessage.setEditable(false);  // 禁止编辑
        JScrollPane spTalkMessage = new JScrollPane(taTalkMessage);
        spTalkMessage.setPreferredSize(new Dimension(400, 200));
        spTalkMessage.setBorder(BorderFactory.createEmptyBorder());
        this.add(spTalkMessage, BorderLayout.CENTER);

        // 按钮组面板
        JPanel btnGroupPanel = new JPanel();
        btnGroupPanel.setBackground(new Color(240, 240, 240));
        this.add(btnGroupPanel, BorderLayout.SOUTH);

        String[] btnTexts = { "断开", "退出" };
        String[] btnActionCommands = { "close", "exit" };
        for (int i = 0; i < btnActionCommands.length; i++) {
            JButton tempBtn = new JButton(btnTexts[i]);
            tempBtn.setActionCommand(btnActionCommands[i]);
            tempBtn.setFont(defaultFont);
            tempBtn.setBackground(new Color(235, 135, 10));
            tempBtn.setForeground(Color.WHITE);
            tempBtn.setFocusPainted(false);
            tempBtn.addActionListener(this);
            btnGroupPanel.add(tempBtn);
        }
        // 设置窗口属性
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setBounds(100, 200, 440, 400);
        this.setVisible(true);
    }

    public static void main(String[] args) {
        TCPServerFrame tsf = new TCPServerFrame();
        tsf.initFrame();
        tsf.changeTalkMessage("请等待客户端连接...");
        tsf.startThread();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String actionCommand = e.getActionCommand();
        if (actionCommand.equals("send")) {
            String message = tfSendMessage.getText();
            if (message.isEmpty()) {
                JOptionPane.showMessageDialog(this, "发送的信息不能为空!");
            } else {
                sendAllMessage(message, true,null);
                tfSendMessage.setText("");
            }
        } else if (actionCommand.equals("close") || actionCommand.equals("exit")) {
            closeServer(actionCommand.equals("exit"));
            Timer timer = new Timer(5000, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.exit(0);// 关闭窗口
                }
            });
            timer.setRepeats(false);  // 确保定时器只执行一次
            timer.start();
            // 弹出提示框告知用户退出
            JOptionPane.showMessageDialog(this, "程序将在5秒后退出.");
        }
    }
    // 关闭服务器端
    private void closeServer(boolean isExit) {
        if (ss != null && !ss.isClosed()) {
            changeTalkMessage("正在断开与客户端的连接，请稍候");
            isServerClose = true;
            if (isExit) {
                isExitServer = true;
            }
            if (!socketList.isEmpty()) {
                sendAllMessage("bye", false,null);
            } else {
                try {
                    ss.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        } else if (isExitServer) {
            System.exit(0);
        }
    }

    @Override
    public void run() {
        try {
            ss = new ServerSocket();
            ss.bind(inetSocketAddress);

            while (!isServerClose) {
                Socket socket = ss.accept();
                socketList.add(socket);
                String client_name = "客户端" + socketList.size();
                clientNames.put(socket, client_name);
                changeTalkMessage(client_name + "连接成功！");

                SocketMode sm = new SocketMode(socket, client_name);
                TalkServerReceiveHelper tsrh = new TalkServerReceiveHelper(sm);
                tsrh.addTalkServerReceiveHelperListener(this);
                tsrh.start();

                Thread.sleep(100);
            }
        } catch (SocketException e1) {
            if (e1.getMessage().contains("socket closed")) {
                changeTalkMessage("连接已关闭!");
            } else {
                e1.printStackTrace();
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        } finally {
            try {
                if (ss != null && !ss.isClosed()) {
                    ss.close();
                }
                changeTalkMessage("服务器已断开连接");
                if (isExitServer) {
                    System.exit(0);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // 发送消息给所有已连接的客户端
    public void sendAllMessage(String message, boolean isPrintMessage, Socket senderSocket) {
        String senderName = "服务器";
        if (senderSocket != null && clientNames.containsKey(senderSocket)) {
            senderName = clientNames.get(senderSocket);
        }
        String formattedMessage = senderName + ": " + message;

        synchronized (socketList) {
            for (Socket socket : socketList) {
                if (socket != senderSocket) {
                    sendMessage(formattedMessage, socket);
                }
            }
        }

        if (isPrintMessage) {
            if (socketList.isEmpty()) {
                changeTalkMessage("没有客户端与服务器连接！");
            } else {
                changeTalkMessage(formattedMessage);
            }
        }
    }


    // 发送消息给特定的客户端
    public void sendMessage(String message, Socket socket) {
        if (socket != null && !socket.isClosed() && socket.isConnected()) {
            try {
                OutputStream os = socket.getOutputStream();
                os.write(message.getBytes());
                os.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void handleClientClose(SocketMode socketMode) {
        Socket socket = socketMode.getSocket();
        if (!isServerClose) {
            this.sendMessage("bye", socket);
            changeTalkMessage(socketMode.getClientName() + "已关闭连接!");
        }
        try {
            socket.close();
            synchronized (socketList) {
                socketList.remove(socket);
                clientNames.remove(socket);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void updateTalkMessage(String message) {
        changeTalkMessage(message);
    }

    @Override
    public void broadcastMessage(SocketMode socketMode, String str) {
        if (!isServerClose) {
            sendAllMessage(str, false, socketMode.getSocket());
        }
    }

    private void changeTalkMessage(String message) {
        SwingUtilities.invokeLater(() -> {
            String temp = taTalkMessage.getText();
            if (!temp.isEmpty()) {
                taTalkMessage.append("\n");
            }
            taTalkMessage.append(message);
        });
    }
    // 启动线程监听客户端连接
    private void startThread() {
        Thread thread = new Thread(this);
        thread.start();
    }
}

